﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Domain.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp;


namespace ERP.Workflow.Designer.Domain
{
    public interface IDefinitionManager: IDomainService
    {
        public Task<Definition> FindAsync(string name, string version=null, bool includeDetails=false);
        public Task<Definition> FindAsync(Guid id, bool includeDetails=false);
        public Task<List<Definition>> FindByNameAsync(string name, bool includeDetails=false);
        public Task<Definition> CreateAsync(Definition definition);
    }
    public class DefinitionManager : DomainService, IDefinitionManager  
    {
        protected readonly IRepository<Definition> _definitionRepository;

        public DefinitionManager(IRepository<Definition> definitionRepository)
        {
            _definitionRepository = definitionRepository;
        }
        public async Task<Definition?> FindAsync(string name, string? version = null, bool includeDetails=false)
        {
            var list = await FindByNameAsync(name, includeDetails);
            var rs= list.WhereIf(!string.IsNullOrEmpty(version), m => m.Version == version)
                .FirstOrDefault();
            return rs;
        }
        public async Task<Definition> FindAsync(Guid id, bool includeDetails = false)
        {
            var rs = Query(includeDetails).First(m=>m.Id==id);
            return await Task.FromResult(rs);
        }
       
        public async Task<Definition> CreateAsync(Definition? definition)
        {
            Check.NotNull(definition.Name, nameof(Definition.Name));
            definition.Version = await NewVersion(definition?.Name);
            return await   _definitionRepository.InsertAsync(definition);
        }
        public Task<List<Definition>> FindByNameAsync(string name, bool includeDetails)
        {
            var rs= Query(includeDetails).Where(m => m.Name == name).ToList();
            return Task.FromResult(rs);
        }
        public async Task<string> NewVersion(string? name)
        {
            var list = await FindByNameAsync(name, false);
            string version =( list.Count + 1).ToString();
            return version;
        }
        private IQueryable<Definition> Query(bool includeDetails = false)
        {
            if (includeDetails)
            {
                var query = _definitionRepository
                     .WithDetailsAsync(
                     m => m.Nodes,
                     m => m.Links,
                     m => m.Labels,
                     m => m.Ports,
                     m => m.Vertices
                     ).Result;

                return query;
            }

            return _definitionRepository.GetQueryableAsync().Result;
        }
    }


}
